package ch.ethz.fcl.metrobuzz.render.interchange.spatial;

import java.util.ArrayList;

import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;

import ch.ethz.fcl.metrobuzz.MBContainer;
import ch.ethz.fcl.metrobuzz.data.interchange.Junction;
import ch.ethz.fcl.metrobuzz.data.interchange.Region;
import ch.ethz.fcl.metrobuzz.data.singapore.SGInterchange;
import ch.ethz.fcl.metrobuzz.data.singapore.SGZone;
import ch.ethz.fcl.metrobuzz.data.texture.MBTexture;
import ch.ethz.fcl.metrobuzz.render.interchange.inter.InterInterchangeRender;
import ch.ethz.fcl.metrobuzz.render.techniques.clip.Clip;
import ch.ethz.fcl.metrobuzz.render.techniques.colors.MBColorTable;
import ch.ethz.fcl.metrobuzz.render.techniques.projection.Projection;
import ch.ethz.fcl.metrobuzz.spatialindex.object2d.Point2D;
import ch.ethz.fcl.metrobuzz.spatialindex.object2d.Polygon;
import ch.ethz.fcl.metrobuzz.spatialindex.object2d.Rectangle;
import ch.ethz.fcl.metrobuzz.spatialindex.object3d.Point3D;
import ch.ethz.fcl.metrobuzz.tools.MBGL;
import ch.ethz.fcl.metrofont.Pen;

public class MultiscaleRender {
	private MBContainer container = null;
	private SGInterchange sr = null;

	public MultiscaleRender(MBContainer container, SGInterchange sr) {
		this.container = container;

		this.sr = sr;
	}

	public void render(Rectangle rec) {
		Clip.clip(rec);
		MBGL.enableBlend();
		int level = SGInterchange.getLevel(container.getViewer().getCamera()
				.getDistance());

		if (level < SGZone.LEVELS)
			renderRegionInterchange(rec, level);
		else
			renderJunctionInterchange(rec);

		Clip.disableClip();
	}

	/**
	 * render region interchange in specified level
	 * 
	 * @param rec
	 * @param level
	 */
	private void renderRegionInterchange(Rectangle rec, int level) {
		renderRegionsBackground(level);
		renderRegionLevelInfo(level);

		for (Region region : sr.getRegions(level))
			region.renderAdjacentBoundary(rec);

		for (Region region : sr.getRegions(level)) {
			region.render(rec, null);
		}

		InterInterchangeRender.render(container.getViewer().getProjection(),
				sr.getRegions(level), 1);
	}

	/**
	 * render mrt stations interchange
	 * 
	 * @param rec
	 */
	private void renderJunctionInterchange(Rectangle rec) {
		ArrayList<Junction> jns = sr.getJunctions();

		// render inter connecting edges between junctions
		// for (int i = 0; i < jns.size(); i++) {
		// Junction jn = jns.get(i);
		// if (jn.isSubway())
		// jn.renderEdges(sr, container.getData().getRoadNetwork());
		// }
		
		// render junctions up edges
		for (int i = 0; i < jns.size(); i++) {
			Junction jn = jns.get(i);
			if (jn.isSubway())
				jn.render(rec, container.getFont());
		}

		InterInterchangeRender.render(container.getViewer().getProjection(),
				jns, 1);
	}

	private void renderRegionsBackground(int level) {
		for (Polygon zone : container.getData().getSGInfo().getSGZones()
				.getZones(level)) {
			zone.renderArea();

			GL11.glLineWidth(2.0f);
			MBColorTable.assignColor(MBColorTable.BLACK, 0.5f);
			zone.render();
		}
	}

	/**
	 * display how many regions in current level
	 * 
	 * @param level
	 */
	private void renderRegionLevelInfo(int level) {
		Projection proj = container.getViewer().getProjection();

		Point3D top_left_point = proj.getWorldCoord(
				new Point2D(Display.getWidth() / 2 - 100,
						Display.getHeight() - 5), 0);
		float width = proj.getWorldDistance(200);
		float height = proj.getWorldDistance(50);
		Rectangle shadowRegion = new Rectangle(top_left_point.getX(),
				top_left_point.getY() - height, top_left_point.getX() + width,
				top_left_point.getY());

		MBTexture.renderTexture(container.getData().getTexture().getShadow(),
				shadowRegion);

		GL11.glColor4f(0, 0, 0, 1);
		String info = sr.getRegions(level).size() + " Regions";
		float fontSize = proj.getWorldDistance(35);
		float infoLen = container.getFont().getLength(info, fontSize);
		container.getFont().display(
				info,
				new Pen(top_left_point.getX() + width / 2 - infoLen / 2,
						top_left_point.getY() + height / 8 - height, fontSize));
	}
}
